package com.lyncs.ods.modules.goods.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.lyncs.ods.common.api.CommonPage;
import com.lyncs.ods.constant.LyncsOdsConstant;
import com.lyncs.ods.modules.goods.model.SkuDetail;
import com.lyncs.ods.modules.goods.model.SkuDetailInfo;
import com.lyncs.ods.modules.goods.model.SkuInfo;
import com.lyncs.ods.modules.goods.mapper.SkuInfoMapper;
import com.lyncs.ods.modules.goods.model.SpuDetail;
import com.lyncs.ods.modules.goods.service.SkuDetailService;
import com.lyncs.ods.modules.goods.service.SkuInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyncs.ods.modules.goods.service.SpuDetailService;
import com.lyncs.ods.utils.PageUtil;
import com.lyncs.ods.utils.SkuUtils;
import com.lyncs.ods.utils.SpuUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * sku信息总表 服务实现类
 * </p>
 *
 * @author alex
 * @since 2022-02-15
 */
@Service
@Slf4j
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {

    @Autowired
    private SkuDetailService skuDetailService;
    @Autowired
    private SpuDetailService spuDetailService;

    @Override
    public CommonPage<SkuDetailInfo> getSkuDetailInfos(Long spuId, @NotNull Long companyId, String keyword, String currency, Map<Long, String> attrs, Integer page, Integer pageSize, String source) {
        List<Long> attrSkuIds = null;
        if (MapUtils.isNotEmpty(attrs)) {
            attrSkuIds = skuDetailService.getSkuIdListByAttrs(spuId, attrs, null, null);
            if (CollectionUtils.isEmpty(attrSkuIds)) {
                return PageUtil.empty(page, pageSize);
            }
        }
        LambdaQueryChainWrapper<SkuInfo> wrapper = this.lambdaQuery()
                .eq(spuId != null, SkuInfo::getSpuId, spuId)
                .eq(SkuInfo::getCompanyId, companyId)
                .in(CollectionUtils.isNotEmpty(attrSkuIds), SkuInfo::getId, attrSkuIds)
                .eq(SkuInfo::getStatus, LyncsOdsConstant.SKUStatus.ENABLE.getKey())
                .and(StringUtils.isNotEmpty(keyword), andWrapper -> andWrapper.like(SkuInfo::getNo, keyword).or().like(SkuInfo::getName, keyword));


        CommonPage<SkuDetailInfo> commonPage = PageUtil.count(wrapper, page, pageSize);
        if (commonPage.getTotal() == 0) {
            return commonPage.setList(List.of());
        }
        List<SkuInfo> skuInfoList = wrapper.last(PageUtil.getLastSql(page, pageSize)).list();
        List<Long> skuIds = skuInfoList.stream().map(SkuInfo::getId).collect(Collectors.toList());
        List<SkuDetail> skuDetails = skuDetailService.lambdaQuery().in(SkuDetail::getSkuId, skuIds)
                .eq(SkuDetail::getStatus, LyncsOdsConstant.SKUStatus.ENABLE.getKey()).list();
        Map<Long, Map<String, String>> skuDetailMap = getSkuAttrs(skuDetails);
        Function<SkuInfo, SkuDetailInfo> func = (info) -> {
            SkuDetailInfo skuDetailInfo = new SkuDetailInfo();
            BeanUtils.copyProperties(info, skuDetailInfo);
            skuDetailInfo.setTransAmount(SkuUtils.toCurrencyAmount(info, currency))
                    .setTransCurrency(currency)
                    .setInnerCode(info.getNo())
                    .setSkuId(info.getId())
                    .setSkuAttrs(skuDetailMap.get(info.getId()))
                    .setAmountJson(info.getAmountJson());
            return skuDetailInfo;
        };
        return PageUtil.result(skuInfoList, func, commonPage);
    }

    @Override
    public Map<Long, Map<String, String>> getSkuAttrs(List<SkuDetail> skuDetails) {
        Map<Long, Map<String, String>> skuAttrMap = new HashMap<>();
        if (CollectionUtils.isEmpty(skuDetails)) {
            return Map.of();
        }
        Map<Long, String> attrNameMap = new HashMap<>();
        List<Long> attrNameIds = skuDetails.stream().map(SkuDetail::getAttrId).filter(attrId -> attrId != 0).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(attrNameIds)) {
            List<SpuDetail> spuDetails = spuDetailService.listByIds(attrNameIds);
            attrNameMap = spuDetails.stream().collect(Collectors.toMap(SpuDetail::getId, SpuUtils::getAttrName));
        }
        Map<Long, List<SkuDetail>> skuDetailMap = skuDetails.stream().collect(Collectors.groupingBy(SkuDetail::getSkuId));
        Map<Long, String> finalAttrNameMap = attrNameMap;
        skuDetailMap.forEach((skuId, details) -> {
            Map<String, String> thisSkuAttrMap = details.stream().collect(Collectors.toMap(detail -> getSkuName(detail, finalAttrNameMap), s -> StringUtils.isEmpty(s.getValue()) ? "" : s.getValue()));
            skuAttrMap.put(skuId, thisSkuAttrMap);
        });
        return skuAttrMap;
    }

    private String getSkuName(SkuDetail skuDetail, Map<Long, String> attrNameMap) {
        return attrNameMap.containsKey(skuDetail.getAttrId()) ? attrNameMap.get(skuDetail.getAttrId()) : skuDetail.getName();
    }
}
